<template>
  <div class="fl-wrap">
    <div class="flow-container" ref="flowContainer"></div>
    <hover-panel :visible.sync="hoverPanelVisible" :selected-node="selectedNode"></hover-panel>
  </div>
</template>

<script>
import { loadLogicFlow } from '@/common/plugins/tools/logicflow'
import { rectNodeConfig } from '@/credit/components/flow/element/theme'
import FlowElement from '@/credit/components/flow/element/install'

import HoverPanel from '@/credit/components/flow/HoverPanel'

import FlowDnd from '@/credit/components/flow/element/dnd/install'
import '@/credit/components/flow/element/dnd/index.scss'

const flowConfig = {
  stopScrollGraph: true,
  stopZoomGraph: true,
  metaKeyMultipleSelected: true,
  isSilentMode: false,
  hideAnchors: true,
  textEdit: false,
  grid: {
    type: 'dot',
    size: 20,
    visible: true,
    config: {
      color: '#ddd',
    },
  },
  keyboard: {
    enabled: true,
  },
  snapline: true,
}

const startX = 80
const startY = 100
const spaceW = rectNodeConfig.width + 50

const enumOneStatusType = {
  0: 'primary',
  1: 'success',
  2: 'danger',
  3: 'warning',
}

const enumMulStatusType = {
  0: 'primary',
  1: 'success',
  2: 'danger',
  3: 'warning',
  4: 'warning',
}

const wfn2Flow = flowData => {
  const nodes = []
  const edges = []

  const n = flowData.length
  nodes.push({
    type: 'flow:start',
    id: 'start_node',
    x: startX,
    y: startY,
    text: '开始',
  })
  edges.push({
    type: 'flow:polyline',
    sourceNodeId: 'start_node',
    targetNodeId: '',
  })

  for (let i = 1; i <= n; i++) {
    const node = flowData[i - 1]
    const { process, status } = node
    const isOneApproval = process.is_one_approval === 1
    const properties = {
      icon: isOneApproval ? 'user' : 'group',
      type: (isOneApproval ? enumOneStatusType : enumMulStatusType)[status] || 'primary',
    }
    nodes.push({
      id: process.wfn_key,
      x: startX + spaceW * i,
      y: startY,
      type: 'flow:user',
      text: process.wfn_name,
      properties,
    })
    edges[i - 1].targetNodeId = process.wfn_key
    edges.push({
      type: 'flow:polyline',
      sourceNodeId: process.wfn_key,
      targetNodeId: '',
      properties,
    })
  }

  nodes.push({
    type: 'flow:end',
    id: 'end_node',
    x: startX + spaceW * (n + 1),
    y: startY,
    text: '结束',
    properties: nodes[n].properties,
  })

  nodes[0].properties = nodes[1].properties
  edges[0].properties = nodes[1].properties
  edges[n].targetNodeId = nodes[n + 1].id
  edges[n].properties = nodes[n].properties

  return {
    nodes,
    edges,
  }
}

export default {
  components: {
    HoverPanel,
  },
  props: {
    flowData: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      loaded: false,
      lf: null,

      hoverPanelVisible: false,
      selectedNode: {},
    }
  },
  computed: {
    lfData() {
      return wfn2Flow(this.flowData)
    },
  },
  watch: {
    lfData: {
      handler: function () {
        this.$nextTick(() => this.flowRender())
      },
      immediate: true,
      deep: true,
    },
  },
  created() {},
  mounted() {},
  methods: {
    async loadFlow() {
      if (this.loaded) return
      await loadLogicFlow()
      window.LogicFlow.use(FlowElement)
      if (!flowConfig.isSilentMode && !flowConfig.hideAnchors && flowConfig.textEdit) {
        window.LogicFlow.use(FlowDnd)
      }
      this.loaded = true
    },

    async flowRender() {
      this.selectedNode = {}
      this.hoverPanelVisible = false

      await this.loadFlow()

      const { flowContainer } = this.$refs
      // 根据宽度自动换行
      const containerWidth = flowContainer.offsetWidth
      const colNum = Math.floor(containerWidth / spaceW)
      for (let i = 0; i < this.lfData.nodes.length; i++) {
        const node = this.lfData.nodes[i]
        const col = i % colNum
        const row = Math.floor(i / colNum)
        node.x = startX + spaceW * (row % 2 === 0 ? col : colNum - col - 1)
        node.y = startY + spaceW * row
      }

      if (!this.lf) {
        this.lf = new window.LogicFlow({
          ...flowConfig,
          container: flowContainer,
        })
        this.initEvent(this.lf)
      }
      this.lf.render(this.lfData)
    },
    initEvent(lf) {
      lf.on('node:mousedown', ({ data }) => {
        if (['start_node', 'end_node'].includes(data.id)) return
        const node = this.flowData.find(it => it.process.wfn_key === data.id)
        this.selectedNode = node || {}
        this.hoverPanelVisible = true
      })
    },

    handleCloseHoverPanel() {
      this.hoverPanelVisible = false
    },
  },
}
</script>

<style lang="scss" scoped>
.flow-container {
  height: 78vh;
  overflow: hidden;
}

.fl-wrap {
  position: relative;
  overflow: hidden;
}
</style>
